iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0
自我挑戰組

菜鳥AI工程師給碩班學弟妹的挑戰系列 第 27

[Day 27] wav2vec2 基礎介紹

  • 分享至 

  • xImage
  •  

前情提要: 昨天透過umap將bert embedding做圖示化,這種模型都是經過大量資料訓練而來,才會有這麼好的效果。

昨天提到了文字方面的模型,今天來提提聲音方面的模型吧。

1. 模型介紹

參考: https://blog.csdn.net/qq_40168949/article/details/128677418
wavlm論文: https://arxiv.org/pdf/2110.13900
有幾個模型wav2vec 2, hubert, wavlm,這些都是用"無標籤"的聲音訓練出來的,所以訓練完的model本身不能直接拿來使用,跟bert一樣需要再用特定資料訓練特定場景,可應用的downstream task
https://ithelp.ithome.com.tw/upload/images/20240831/20168446J5ErAuLlbN.png

  • Speaker Identification (SID), Automatic Speaker Verification (ASV), Speaker Diarization (SD),

  • Phoneme Recognition (PR), Automatic Speech Recognition
    (ASR), Keyword Spotting (KS),

  • Speech Translation (ST)

  • Emotion Recognition (ER),

  • Speech Enhancement (SE), Speech Separation (SS) and Voice
    Conversion (VC).

主要會分成以上這幾種,基本上應用的場景很多,我自己本身是有做過情緒辨識效果上還不錯。

2. Emotion Recognition

這裡透過這個例子來看看如何使用吧~

參考: https://github.com/m3hrdadfi/soxan
流程圖(參考圖片: https://www.semanticscholar.org/reader/f1eb9232314480050400fe52abd75f128da7cc86 )

https://ithelp.ithome.com.tw/upload/images/20240831/201684466FzxGKJ0Q6.png

上面github的colab程式片段: https://colab.research.google.com/github/m3hrdadfi/soxan/blob/main/notebooks/Emotion_recognition_in_Greek_speech_using_Wav2Vec2.ipynb#scrollTo=Fv62ShDsH5DZ

  • 聲音 → Wav2Vec2 → embedding → MLP → 分類結果

MLP其實就是多個nn.Linear組合合成,在我們之前範例也有運用過,那這個範例透過transformers來呼叫wav2vec2,甚至現在可以透過torchaudio來直接呼叫 (https://pytorch.org/audio/main/generated/torchaudio.pipelines.Wav2Vec2Bundle.html#torchaudio.pipelines.Wav2Vec2Bundle ),就可以抽取出embedding囉

import torch
import torch.nn as nn
from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss

from transformers.models.wav2vec2.modeling_wav2vec2 import (
    Wav2Vec2PreTrainedModel,
    Wav2Vec2Model
)


class Wav2Vec2ClassificationHead(nn.Module):
    """Head for wav2vec classification task."""
    # 使用MLP來分類
    def __init__(self, config):
        super().__init__()
        self.dense = nn.Linear(config.hidden_size, config.hidden_size)
        self.dropout = nn.Dropout(config.final_dropout)
        self.out_proj = nn.Linear(config.hidden_size, config.num_labels)

    def forward(self, features, **kwargs):
        x = features
        x = self.dropout(x)
        x = self.dense(x)
        x = torch.tanh(x)
        x = self.dropout(x)
        x = self.out_proj(x)
        return x


class Wav2Vec2ForSpeechClassification(Wav2Vec2PreTrainedModel):
    def __init__(self, config):
        super().__init__(config)
        self.num_labels = config.num_labels
        self.pooling_mode = config.pooling_mode
        self.config = config

        self.wav2vec2 = Wav2Vec2Model(config) # 呼叫transformers的模型
        self.classifier = Wav2Vec2ClassificationHead(config) # MLP

        self.init_weights()

    def freeze_feature_extractor(self):
        self.wav2vec2.feature_extractor._freeze_parameters()

    def merged_strategy(
            self,
            hidden_states,
            mode="mean"
    ):
        if mode == "mean":
            outputs = torch.mean(hidden_states, dim=1)
        elif mode == "sum":
            outputs = torch.sum(hidden_states, dim=1)
        elif mode == "max":
            outputs = torch.max(hidden_states, dim=1)[0]
        else:
            raise Exception(
                "The pooling method hasn't been defined! Your pooling mode must be one of these ['mean', 'sum', 'max']")

        return outputs

    def forward(
            self,
            input_values,
            attention_mask=None,
            output_attentions=None,
            output_hidden_states=None,
            return_dict=None,
            labels=None,
    ):
        return_dict = return_dict if return_dict is not None else self.config.use_return_dict
        outputs = self.wav2vec2(
            input_values,
            attention_mask=attention_mask,
            output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,
            return_dict=return_dict,
        )
        hidden_states = outputs[0] 
        hidden_states = self.merged_strategy(hidden_states, mode=self.pooling_mode)
        logits = self.classifier(hidden_states)

這裡只是透過範例來講解怎麼用,如果實際想訓練可以直接用他的github,但因為是三年前了,可能有些程式會有問題。

在聲音方面也有這種大型的pre-trained model,另外目前比較常看到的是用wavlm加進TTS,讓你能用5~30s的聲音來zero-shot出你的聲音,不然ASR的部分基本上會用whisper,比較少在用這幾個了,不過做為學習可以用這個當出發點。

另外就是為甚麼需要大型的pre-trained model,在做情緒辨識和一些專案我體驗蠻多的,最主要就是減少overfitting,因為他們已經拿了大量資料來訓練,已經看過各個場景,那你透過downstream讓他focus在某個場景,可以想像他已經有很多經驗,所以用這些經驗來判斷效果當然比較好。

這兩天都沒有談論本身model細節,我認為先會拿來使用比較重要,等到累積的經驗夠了,或哪天你需要做這塊,那就再去研究即可。

今天就先到這裡囉~


上一篇
[Day 26] LitServe總結 + umap圖示化bert
下一篇
[Day 28] 模型蒸餾觀念介紹
系列文
菜鳥AI工程師給碩班學弟妹的挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言